//-----------------------------------------------------------------------
// <copyright file="DevEnv.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// </copyright>
// <author>Andy Reeves [Updated: 22-2-08 Mike Fourie. Code Cleanup]</author>
// <email>andyr</email>
// <date>2004-03-23</date>
// <summary>Wraps a call to DevEnv.exe</summary>
//-----------------------------------------------------------------------
namespace Microsoft.Sdc.Tasks.Tools
{
    using System;
    using System.IO;
    using System.Globalization;
    using Microsoft.Win32;
    using Microsoft.Build.Framework;
    using Microsoft.Build.Utilities;

    /// <summary>
    /// Executes DevEnv.exe to build the .sln file specified.
    /// </summary>    
    /// <remarks>
    /// <code><![CDATA[<Tools.DevEnv VisualStudio="visualStudio" Path="path" Config="config" OutputFolder="outputFolder" Clean="clean" /> ]]></code>
    /// <para>where:</para>
    /// <para><i>visualStudio (Required)</i></para>
    /// <para>The version of Visual Studio to use. Specify 7.0, 7.1 or 8.0.</para>
    /// <para><i>path (Required)</i></para>
    /// <para>The path to the .sln file.</para>
    /// <para><i>config (Required)</i></para>
    /// <para>The solution configuration to build. Typically, Debug or Release.</para>
    /// <para>If multiple platforms are possible, the name must also contain platform name.</para>
    /// <para>for example: "Debug|Win32"</para>
    /// <para><i>outputFolder</i></para>
    /// <para>If specified, the folder to write the DevEnv output to.</para>
    /// <para><i>clean</i></para>
    /// <para>True to pass the Clean command line argument to DevEnv.exe</para>
    /// </remarks>
    /// <example>
    /// <code><![CDATA[
    /// <Project>
    ///     <Target Name="Test" >
    ///         <Tools.DevEnv
    ///             VisualStudio="8.0"
    ///             Path="$(MSBuildProjectDirectory)\..\Solutions\MainSolution\Main.sln"
    ///             Config="Release"
    ///             OutputFolder="$(MSBuildProjectDirectory)\Output\Main"
    ///             Clean="true">
    ///           <Output TaskParameter="ExitCode" PropertyName="MyExitCode"></Output>
    ///         </Tools.DevEnv>
    ///         <Message Condition=" '$(MyExitCode) != '0' " Text="ExitCode was non-zero" />
    ///     </Target>
    /// </Project>
    /// ]]></code>    
    /// </example>
    public sealed class DevEnv : ToolTaskBase
    {
        #region Public Properties

        /// <summary>
        /// Gets or sets the path.
        /// </summary>
        /// <value>The path.</value>
        [Required]
        public string Path
        {
            get { return (string)Bag["Path"]; }
            set { Bag["Path"] = value; }
        }

        /// <summary>
        /// Gets or sets the config.
        /// </summary>
        /// <value>The config.</value>
        [Required]
        public string Config
        {
            get { return (string)Bag["Config"]; }
            set { Bag["Config"] = value; }
        }

        /// <summary>
        /// Gets or sets the visual studio version
        /// </summary>
        /// <value>The visual studio version.</value>
        [Required]
        public string VisualStudio
        {
            get { return (string)Bag["VisualStudio"]; }
            set { Bag["VisualStudio"] = value; }
        }

        /// <summary>
        /// Gets or sets of Clean command line argument to DevEnv.exe.
        /// </summary>
        /// <value><c>true</c> if clean; otherwise, <c>false</c>.</value>
        public bool Clean
        {
            get { return (bool)Bag["Clean"]; }
            set { Bag["Clean"] = value; }
        }

        /// <summary>
        /// Gets or sets the output folder.
        /// </summary>
        /// <value>The output folder.</value>
        public string OutputFolder
        {
            get { return (string)Bag["OutputFolder"]; }
            set { Bag["OutputFolder"] = value; }
        }

        /// <summary>
        /// Gets or sets the name of the output file.
        /// </summary>
        /// <value>The name of the output file.</value>
        public string OutputFileName
        {
            get { return (string)Bag["OutputFileName"]; }
            set { Bag["OutputFileName"] = value; }
        }
        #endregion

        /// <summary>
        /// The name of the exe we call.
        /// </summary>
        /// <value>The name of the exe we call.</value>
        protected override string ToolName
        {
            get { return "devenv.exe"; }
        }

        /// <summary>
        /// Performs the action of this task.
        /// </summary>
        protected override void InternalExecute()
        {
            #region Execute code

            // reset the exitcode
            this.ExitCode = 0;

            FileInfo fi = new FileInfo(this.Path);
            string solutionFileName = fi.Name;

            if (this.OutputFolder == null || this.OutputFolder.Length == 0)
            {
                this.OutputFolder = System.IO.Path.Combine(Environment.CurrentDirectory, "Output");
            }

            if (this.OutputFileName == null || this.OutputFileName.Length == 0)
            {
                // Replace invalid file name character used in mixed platform configurations
                string fileNameSafeConfig = this.Config.Replace("|", " ");
                this.OutputFileName = String.Format(CultureInfo.InvariantCulture, "{0}.{1}.txt", solutionFileName, fileNameSafeConfig);
            }

           string outputFilePath = System.IO.Path.Combine(this.OutputFolder, this.OutputFileName);
           Directory.CreateDirectory(this.OutputFolder);
            if (System.IO.File.Exists(outputFilePath))
            {
                System.IO.File.Delete(outputFilePath);
            }

            Log.LogMessageFromResources("Solution.Build", this.Config, solutionFileName);

            CommandLineBuilder commandLineBuilder = new CommandLineBuilder();
            commandLineBuilder.AppendSwitch(String.Format(CultureInfo.InvariantCulture, "/{0}", (this.Clean ? "rebuild" : "build")));
            commandLineBuilder.AppendSwitch("\"" + this.Config + "\"");
            commandLineBuilder.AppendSwitch("/out \"" + outputFilePath + "\"");
            commandLineBuilder.AppendSwitch("\"" + this.Path + "\"");

            this.ExitCode = ExecuteTool(this.ComputePathToTool(), String.Empty, commandLineBuilder.ToString());
            
            #endregion
        }

        /// <summary>
        /// Full calculated path to tool including exe name
        /// </summary>
        /// <returns>Defaults to default install location of devenv.exe</returns>
        protected override string GenerateFullPathToTool()
        {
            if (this.VisualStudio.Length == 0)
            {
                this.VisualStudio = "7.0";
            }

            RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\VisualStudio\" + this.VisualStudio);

            string pathToVS = Convert.ToString(key.GetValue("InstallDir"), CultureInfo.InvariantCulture);
            key.Close();
            return System.IO.Path.Combine(pathToVS, this.ToolName);
        }        
    }
}
